package com.grace.service;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.grace.dao.SysAclMapper;
import com.grace.dao.SysAclModuleMapper;
import com.grace.dao.SysDeptMapper;
import com.grace.dto.AclDto;
import com.grace.dto.AclModuleLevelDto;
import com.grace.dto.DeptLevelDto;
import com.grace.model.SysAcl;
import com.grace.model.SysAclModule;
import com.grace.model.SysDept;
import com.grace.util.LevelUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 树结构
 */
@Service
public class SysTreeService {
    //引入mapper,写获取空格列表的方法
    @Resource
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private SysAclModuleMapper sysAclModuleMapper;

    @Autowired
    private SysCoreService sysCoreService;

    @Autowired
    private SysAclMapper sysAclMapper;

    public List<AclModuleLevelDto> userAclTree(int userId) {
        //获取用户已分配的权限点
        List<SysAcl> userAclList = sysCoreService.getUserAclList(userId);
        List<AclDto> aclDtoList = Lists.newArrayList();

        //遍历判断是否可访问，是否有权限处理，将这 个数据加入到权限List中
        for (SysAcl acl : userAclList) {
            AclDto dto = AclDto.adapt(acl);
            dto.setHasAcl(true);
            dto.setChecked(true);
            aclDtoList.add(dto);
        }
        return aclListToTree(aclDtoList);
    }


    /**
     * 角色-权限模块树
     */
    public List<AclModuleLevelDto> roleTree(int roleId) {
        //1、当前用户已分配的权限点
        List<SysAcl> userAclList = sysCoreService.getCurrentUserList();

        //2.当前角色已分配的权限点
        List<SysAcl> roleAclList = sysCoreService.getRoleAclList(roleId);
        //3.当前系统所有权限点
        List<AclDto> aclDtoList = Lists.newArrayList();

        //将当前用户已分配的权限点的集合的所有id，构成一个Set
        //map方法是将当前的某一个对象映射成我们需要的一个值
        Set<Integer> userAclIdSet = userAclList.stream().map(sysAcl -> sysAcl.getId()).collect(Collectors.toSet());
        Set<Integer> roleAclIdSet = roleAclList.stream().map(sysAcl -> sysAcl.getId()).collect(Collectors.toSet());

        /* 得到已分配的权限集合
        //取下两者的并集
        Set<SysAcl> aclSet = new HashSet<>(roleAclList);
        aclSet.addAll(userAclList);
        */

        //得到整个的权限集合
        List<SysAcl> allAclList = sysAclMapper.findAll();
//        Set<SysAcl> aclSet = new HashSet<>(allAclList);

//        for (SysAcl acl : aclSet) {
        //遍历判断是否可访问，是否有权限处理，将这个数据加入到权限List中
        for (SysAcl acl : allAclList) {
            AclDto dto = AclDto.adapt(acl);
            if (userAclIdSet.contains(acl.getId())) {
                dto.setHasAcl(true);
            }
            if (roleAclIdSet.contains(acl.getId())) {
                dto.setChecked(true);
            }
            aclDtoList.add(dto);
        }
        return aclListToTree(aclDtoList);
    }

    /**
     * 将权限点转换成树
     */
    public List<AclModuleLevelDto> aclListToTree(List<AclDto> aclDtoList) {
        if (CollectionUtils.isEmpty(aclDtoList)) {
            return Lists.newArrayList();
        }
        //拿到之前的模块树
        List<AclModuleLevelDto> aclModuleLevelList = aclModuleTree();
        //得到辅助map
        Multimap<Integer, AclDto> moduleIdAclMap = ArrayListMultimap.create();
        for (AclDto aclDto : aclDtoList) {
            //当状态值为可用时
            if (aclDto.getStatus() == 1) {
                moduleIdAclMap.put(aclDto.getAclModuleId(), aclDto);
            }
        }
        //通过递归完成aclModuleLevelList的封装
        bindAclsWithOrder(aclModuleLevelList, moduleIdAclMap);
        return aclModuleLevelList;
    }

    /**
     * 通过递归完成aclModuleLevelList的封装
     */
    public void bindAclsWithOrder(List<AclModuleLevelDto> aclModuleLevelList, Multimap<Integer, AclDto> moduleIdAclMap) {
        if (CollectionUtils.isEmpty(aclModuleLevelList)) {
            return;
        }
        for (AclModuleLevelDto dto : aclModuleLevelList) {
            List<AclDto> aclDtoList = (List<AclDto>) moduleIdAclMap.get(dto.getId());
            if (CollectionUtils.isNotEmpty(aclDtoList)) {
                Collections.sort(aclDtoList, aclSeqComparator);
                dto.setAclList(aclDtoList); //原来这里忘写了。。
            }
            bindAclsWithOrder(dto.getAclModuleDtoList(), moduleIdAclMap);
        }
    }

    /**
     * 角色权限模块排序方法（升序）
     */
    public Comparator<AclDto> aclSeqComparator = new Comparator<AclDto>() {
        @Override
        public int compare(AclDto o1, AclDto o2) {
            return o1.getSeq() - o2.getSeq();
        }
    };

    /**
     * 权限模块树主方法
     *
     * @return
     */
    public List<AclModuleLevelDto> aclModuleTree() {

        List<SysAclModule> sysAclModuleList = sysAclModuleMapper.getAllAclModule();
        List<AclModuleLevelDto> dtoList = Lists.newArrayList();
        //调用拷贝函数，完成dtoList的封装
        for (SysAclModule aclModule : sysAclModuleList) {
            AclModuleLevelDto dto = AclModuleLevelDto.adapt(aclModule);
            dtoList.add(dto);
        }
        //调用: 生成权限模块树方法
        return aclModuleListToTree(dtoList);
    }

    /**
     * 生成权限模块树方法
     */
    public List<AclModuleLevelDto> aclModuleListToTree(List<AclModuleLevelDto> aclModuleLevelList) {
        //防止出现空指针异常
        if (CollectionUtils.isEmpty(aclModuleLevelList)) {
            return Lists.newArrayList();
        }
        //定义用来辅助map
        Multimap<String, AclModuleLevelDto> levelDtoMultimap = ArrayListMultimap.create();
        //定义树根
        List<AclModuleLevelDto> rootList = Lists.newArrayList();
        //初始化辅助map和树根
        for (AclModuleLevelDto dto : aclModuleLevelList) {
            levelDtoMultimap.put(dto.getLevel(), dto);
            //如果是root的话，插入到rootList中
            if (LevelUtil.ROOT.equals(dto.getLevel())) {
                rootList.add(dto);
            }
        }
        //使用字段seq进行升序排序
        Collections.sort(rootList, dtoAclModuleComparator);
        //层级遍历生成模块树
        transformAclModuleTree(rootList, LevelUtil.ROOT, levelDtoMultimap);
        //返回该树
        return rootList;
    }

    /**
     * 权限模块排序方法（升序）
     */
    public Comparator<AclModuleLevelDto> dtoAclModuleComparator = new Comparator<AclModuleLevelDto>() {
        @Override
        public int compare(AclModuleLevelDto o1, AclModuleLevelDto o2) {
            return o1.getSeq() - o2.getSeq();
        }
    };

    /**
     * 层级遍历树
     */
    private void transformAclModuleTree(List<AclModuleLevelDto> aclModuleLevelList, String level, Multimap<String, AclModuleLevelDto> levelDtoMultimap) {
        //遍历每个节点
        for (int i = 0; i < aclModuleLevelList.size(); i++) {
            //获取当前层对象
            AclModuleLevelDto aclModuleLevelDto = aclModuleLevelList.get(i);
            //获取当前层的level
            String nextLevel = LevelUtil.calculateLevel(level, aclModuleLevelDto.getId());
            //获取当前层所拥有的的列表
            List<AclModuleLevelDto> tempAclModuleList = (List<AclModuleLevelDto>) levelDtoMultimap.get(nextLevel);
            //如果子部门不为空,将子部门进行排序后插入子部门的List，再进行递归，寻找子部门的子部门
            if (CollectionUtils.isNotEmpty(tempAclModuleList)) {
                Collections.sort(tempAclModuleList, dtoAclModuleComparator);
                aclModuleLevelDto.setAclModuleDtoList(tempAclModuleList);
                transformAclModuleTree(tempAclModuleList, nextLevel, levelDtoMultimap);
            }
        }

    }


    /**
     * 部门树方法
     * 说白了就是将获取到的部门存入dtoList集合中
     *
     * @return 部门树的集合
     */
    public List<DeptLevelDto> deptTree() {
        //获取所有部门列表
        List<SysDept> sysDeptList = sysDeptMapper.getAllDept();
        //新建一个集合dtoList
        List<DeptLevelDto> dtoList = Lists.newArrayList();
        //循环存入对比值
        for (SysDept dept : sysDeptList) {
            DeptLevelDto dto = DeptLevelDto.adapt(dept);
            dtoList.add(dto);
        }
        //1.得到数据库查询的部门之后，调用dtoListToTree方法，把杂乱的数据变成我想要的树
        return dtoListToTree(dtoList);
    }

    /**
     * 通过递归把tree组装起来（层级遍历树）
     *
     * @param deptLevelList
     * @return
     */
    public List<DeptLevelDto> dtoListToTree(List<DeptLevelDto> deptLevelList) {
        //判断非空(如果是空的话，返回一个空的List)
        if (CollectionUtils.isEmpty(deptLevelList)) {
            return Lists.newArrayList();
        }
        //import com.google.common.collect.Multimap;
        //string==level dto==对应我们的列表 Map<String,List<object>>
        //定义一个特殊的数据结构（用来做辅助参数）
        //level -> [dept1, dept2, ...]
        Multimap<String, DeptLevelDto> levelDtoMultimap = ArrayListMultimap.create();
        //声明rootList作为根List 一级部门
        List<DeptLevelDto> rootList = Lists.newArrayList();
        //开始循环取值
        for (DeptLevelDto dto : deptLevelList) {
            //每次获取我的dto层级的时候，把dto插入进去 得到完整的数据
            levelDtoMultimap.put(dto.getLevel(), dto);
            //判断如果当前部门是顶级部门（ROOT部门）
            if (LevelUtil.ROOT.equals(dto.getLevel())) {
                //加入到rootList里面 得到树根
                rootList.add(dto);
            }
        }
        //按照seq进行从小到大的顺序进行排序（升序）
        Collections.sort(rootList, new Comparator<DeptLevelDto>() {
            //自定义排序
            @Override
            public int compare(DeptLevelDto o1, DeptLevelDto o2) {
                return o1.getSeq() - o2.getSeq();
            }
        });

        //递归产生树
        transformDeptTree(rootList, LevelUtil.ROOT, levelDtoMultimap);

        return rootList;
    }

    /**
     * 对当前层级的处理
     *
     * @param deptLevelList     当前层级的部门列表
     * @param level             层级
     * @param levelDeptMultimap 辅助参数
     */
    public void transformDeptTree(List<DeptLevelDto> deptLevelList, String level, Multimap<String, DeptLevelDto> levelDeptMultimap) {
        for (int i = 0; i < deptLevelList.size(); i++) {
            //遍历该层的每一个元素
            DeptLevelDto deptLevelDto = deptLevelList.get(i);

            //处理当前层的数据
            String nextLevel = LevelUtil.calculateLevel(level, deptLevelDto.getId());//参数是parentId

            //处理下一层
            List<DeptLevelDto> tempDeptList = (List) levelDeptMultimap.get(nextLevel);

            //排序交换处理
            if (CollectionUtils.isNotEmpty(tempDeptList)) {
                //排序
                Collections.sort(tempDeptList, dtoComparator);
                //设置下一层部门
                deptLevelDto.setDeptLevelDtoList(tempDeptList);
                //进入到下一层(递归）
                transformDeptTree(tempDeptList, nextLevel, levelDeptMultimap);
            }
        }
    }

    /**
     * 排序方法（升序）
     */
    public Comparator<DeptLevelDto> dtoComparator = new Comparator<DeptLevelDto>() {
        @Override
        public int compare(DeptLevelDto o1, DeptLevelDto o2) {
            return o1.getSeq() - o2.getSeq();
        }
    };


}
